package com.emperor.core.app;

import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.vafada.swtcalendar.SWTCalendarDialog;
import org.vafada.swtcalendar.SWTCalendarEvent;
import org.vafada.swtcalendar.SWTCalendarListener;

import com.emperor.cashier.app.CashierAppForm;
import com.emperor.core.logic.BizModel;
import com.emperor.employee.logic.Employee;
import com.emperor.inventory.app.InventoryAppCtrl;
import com.emperor.misc.app.HelpAppCtrl;
import com.emperor.user.logic.User;
import com.emperor.util.DateFormatter;
import com.swtdesigner.SWTResourceManager;

public class AppBase implements App {

	protected Map<String, Object> params;
	private SimpleDateFormat sdf = new SimpleDateFormat(DateFormatter.YYYYMMDD);
	static Logger log = Logger.getLogger(AppBase.class);
	protected Shell shell;

	public Map<String, Object> getParams() {
		return this.params;
	}

	public void setParams(Map<String, Object> params) {
		this.params = params;
	}

	// sub class must overwrite this method for sure.
	public void open() {

	}

	public BizModel setModel(Composite composite, BizModel model) {
		return setModel(composite, null, model);
	}

	// in this DIY framework, all element name must have tooltiptext, otherwise
	// will
	// be abandoned
	public BizModel setModel(Composite composite, String prefix, BizModel model) {
		List<String> fieldNames = model.getFieldNames();
		Control[] controls = composite.getChildren();
		Map<String, Object> params = new HashMap<String, Object>();
		if (controls != null && controls.length > 0) {
			for (int i = 0; i < controls.length; i++) {
				if (controls[i] != null && controls[i].getToolTipText() != null) {
					String fieldName = controls[i].getToolTipText();

					if (prefix != null && fieldName.indexOf("_") != -1) {
						fieldName = fieldName.substring(
								fieldName.indexOf("_") + 1, fieldName.length());

					}
					if (fieldNames.contains(fieldName)) {
						String text = getText(controls[i]);
						params.put(fieldName, text.trim());
						log.info(fieldName + "|" + text);
					}
				}
			}
		}

		model.setValues(params);
		return model;
	}

	public void setControls(Composite composite, String prefix, BizModel model) {
		List<String> fieldNames = model.getFieldNames();
		Control[] controls = composite.getChildren();
		Map<String, Object> params = model.getValues();
		if (controls != null && controls.length > 0 && !params.isEmpty()) {
			for (int i = 0; i < controls.length; i++) {
				String fieldName = controls[i].getToolTipText();

				if (prefix != null && fieldName != null
						&& fieldName.indexOf("_") != -1) {
					fieldName = fieldName.substring(fieldName.indexOf("_") + 1,
							fieldName.length());
				}

				if (fieldNames.contains(fieldName)
						&& params.containsKey(fieldName)) {
					setText(controls[i], params.get(fieldName));
				}
			}
		}
	}

	// TODO: need to update this with more control in the future.
	private String getText(Control control) {
		StringBuffer sb = new StringBuffer();

		if (control instanceof org.eclipse.swt.widgets.List) {
			org.eclipse.swt.widgets.List list = (org.eclipse.swt.widgets.List)control;
			String[] selections = list.getSelection();
			if (selections != null && selections.length > 0) {
				for (int i=0; i<selections.length; i++) {
					if (!StringUtils.isEmpty(selections[i])) {
						sb.append(selections[i]);
						break;	
					}
				}
			}
		} else
		if (control instanceof Text) {
			Text text = (Text) control;
			sb.append(text.getText());
		} else
		if (control instanceof Combo) {
			Combo combo = (Combo) control;
			sb.append(combo.getText());
		}
		else {
			if (control.getData() != null) {
				sb.append(control.getData().toString());	
			}
		}
		return sb.toString();
	}

	// TODO: need to update this with more control in the future
	private void setText(Control control, Object value) {
		if (control instanceof Text) {
			Text text = (Text) control;
			if (value != null) {
				if (value instanceof String) {
					text.setText((String) value);
				} else if (value instanceof Date) {
					text.setText(sdf.format((Date) value));
				} else {
					text.setText(value.toString());
				}
			}
		} else if (control instanceof Label) {
			Label label = (Label)control;
			if (value != null) {
				if (value instanceof String) {
					label.setText((String) value);
				} else if (value instanceof Date) {
					label.setText(sdf.format((Date) value));
				} else {
					label.setText(value.toString());
				}
			}
		} else if (control instanceof org.eclipse.swt.widgets.List) {
			org.eclipse.swt.widgets.List list = (org.eclipse.swt.widgets.List)control;
			if (value != null) {
				if (value instanceof String) {
					String[] items = list.getItems();
					if (items != null && items.length > 0) {
						for (int i=0; i<items.length; i++) {
							if (items[i].equals(value)) {
								list.select(i);
								break;
							}
						}
					}
				}
			}
		} else if (control instanceof Combo) {
			Combo combo = (Combo)control;
			if (value != null && combo.getItems() != null) {
				if (value instanceof String) {
					String[] items = combo.getItems();
					for (int i=0; i<items.length; i++) {
						if (items[i].equals(value)) {
							combo.select(i);
							break;
						}
					}
				}
			}
		}
	}

	public BizModel preAdd(BizModel model, Map<String, Object> params) {
		if (params.get(AppConstant.USER) != null) {
			User user = (User) params.get(AppConstant.USER);
			Employee employee = user.getEmployee();

			Date today = new Date();
			model.setCrtby(employee.getId());
			model.setCrtdate(today);
			model.setUpdby(employee.getId());
			model.setUpddate(today);
		}
		return model;
	}

	public BizModel preUpdate(BizModel model, Map<String, Object> params) {
		if (params.get(AppConstant.USER) != null) {
			User user = (User) params.get(AppConstant.USER);
			Employee employee = user.getEmployee();

			Date today = new Date();
			model.setUpdby(employee.getId());
			model.setUpddate(today);
		}
		return model;
	}

	public void centreShell(Shell shell) {
		Rectangle pDisplayBounds = shell.getDisplay().getBounds();
		Rectangle pShellBounds = shell.getBounds();

		int nLeft = (pDisplayBounds.width - pShellBounds.width) / 2;
		int nTop = (pDisplayBounds.height - pShellBounds.height) / 2;

		shell.setBounds(nLeft, nTop, pShellBounds.width, pShellBounds.height);
	}
	
	public void initScreen(Shell shell, Map<String, Object> params) {
		centreShell(shell);
		shell.setMaximized((Boolean)params.get(AppConstant.FULL_SCREEN));
	}

	public void pickDate(Shell shell, final Text text) {
		SWTCalendarDialog dialog = new SWTCalendarDialog(shell.getDisplay());
		dialog.addDateChangedListener(new SWTCalendarListener() {
			public void dateChanged(SWTCalendarEvent calendarEvent) {
				text.setText(sdf
						.format(calendarEvent.getCalendar().getTime()));
			}
		});
		
		if (text.getText() != null && text.getText().length() > 0) {
			try {
				Date d = sdf.parse(text.getText());
				dialog.setDate(d);
			} catch (Exception ex) {
			}
		}
		dialog.open();
	}
	
	public Shell getShell() {
		return this.shell;
	}

	@Override
	public void gotoAbout(Shell shell, Map<String, Object> params) {
		params.put(AppConstant.APPCTRL, HelpAppCtrl.HELP_CTRL);
		params.put(AppConstant.ACTION, HelpAppCtrl.HELP_ABT);
		shell.close();
	}

	@Override
	public void gotoExit(Shell shell, Map<String, Object> params) {
		params.put(AppConstant.ONLINE, new Boolean(false));
		shell.close();
	}

	@Override
	public void gotoHelp(Shell shell, Map<String, Object> params) {
		params.put(AppConstant.APPCTRL, HelpAppCtrl.HELP_CTRL);
		params.put(AppConstant.ACTION, HelpAppCtrl.HELP_ENQ);
		shell.close();
	}

	@Override
	public void gotoLogout(Shell shell, Map<String, Object> params) {
		params.put(AppConstant.APPCTRL, null);
		params.put(AppConstant.USER, null);
		shell.close();
	}

	@Override
	public void buildStandardMenu(final Shell shell, final Map<String, Object> params, final String ctrl, final String action) {
		final ToolBar toolBar = new ToolBar(shell, SWT.RIGHT);
		toolBar.setBounds(0, 0, 545, 40);

		final ToolItem newItemToolItem = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				params.put(AppConstant.APPCTRL, ctrl);
				params.put(AppConstant.ACTION, action);
				shell.close();
			}
		});
		newItemToolItem.setImage(SWTResourceManager.getImage(CashierAppForm.class, "/img/Arrow-Right.png"));
		newItemToolItem.setText("Back");
		
		final ToolItem newItemToolItem_1 = new ToolItem(toolBar, SWT.PUSH);
		newItemToolItem_1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				gotoHelp(shell, params);
			}
		});
		newItemToolItem_1.setImage(SWTResourceManager.getImage(CashierAppForm.class, "/img/Help.png"));
		newItemToolItem_1.setText("Help");
	}

	@Override
	public int message(Shell shell, String text, String message) {
		return message(shell, text, message, null);
	}
	
	@Override
	public int message(Shell shell, String text, String message, Integer status) {
		MessageBox box = null;
		if (status == null) {
			box = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
		} else {
			box = new MessageBox(shell, status);
		}
		box.setText(text);
		box.setMessage(message);
		return box.open();
	}
	
	@Override
	public int message(Shell shell, String text, List<String> errors, Integer status) {
		MessageBox box = null;
		if (status == null) {
			box = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
		} else {
			box = new MessageBox(shell, status);
		}
		box.setText(text);

		if (errors != null && !errors.isEmpty()) {
			StringBuffer sb = new StringBuffer();
			for (Iterator<String> iter = errors.iterator(); iter.hasNext();) {
				String error = iter.next();
				sb.append(error).append("\n");
			}
			box.setMessage(sb.toString());
		}
		
		return box.open();
	}
}
